home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / Other Langs / MacPerl ƒ / Perl Source ƒ / MacPerl / MPDrop.c < prev    next >
C/C++ Source or Header  |  1993-11-07  |  7KB  |  344 lines

  1. /*********************************************************************
  2. Project    :    MacPerl            -    Real Perl Application
  3. File        :    MPDrop.c            -    Droplets
  4. Author    :    Matthias Neeracher
  5. Started    :    02Oct93                                Language    :    MPW C
  6. Modified    :    02Oct93    MN    Compiles correctly
  7. Last        :    02Oct93
  8. *********************************************************************/
  9.  
  10. #include <Dialogs.h>
  11. #include <QuickDraw.h>
  12. #include <Windows.h>
  13. #include <Menus.h>
  14. #include <Fonts.h>
  15. #include <AppleEvents.h>
  16. #include <AERegistry.h>
  17. #include <Processes.h>
  18. #include <files.h>
  19. #include <StandardFile.h>
  20. #include <Aliases.h>
  21. #include <GestaltEqu.h>
  22. #include <Folders.h>
  23. #include <Errors.h>
  24. #include <Resources.h>
  25.  
  26. #pragma segment Main
  27.  
  28. #define FAILOSERR(call) if (err = call) return err; else 0
  29.  
  30. Boolean        gQuitting;
  31. FSSpec        gMySelf;
  32. EventRecord    gLastEvent;
  33.  
  34. pascal Boolean CheckEnvironment()
  35. {
  36.     long    result;
  37.     
  38.     if (Gestalt(gestaltAppleEventsAttr, &result))
  39.         return false;
  40.         
  41.     return (result & (1 << gestaltAppleEventsPresent)) != 0;
  42. }  /* CheckEnvironment */
  43.  
  44. /* The following stuff is adapted from Jens Peter Alfke's SignatureToApp code */
  45.  
  46. OSErr MacPerlRunning(ProcessSerialNumber *psn)
  47. {
  48.     OSErr err;
  49.     ProcessInfoRec info;
  50.     
  51.     psn->highLongOfPSN = 0;
  52.     psn->lowLongOfPSN  = kNoProcess;
  53.     do    {
  54.         FAILOSERR(GetNextProcess(psn));
  55.             
  56.         info.processInfoLength     = sizeof(info);
  57.         info.processName             = nil;
  58.         info.processAppSpec         = nil;
  59.         
  60.         FAILOSERR(GetProcessInformation(psn, &info));
  61.     } while(info.processSignature != 'McPL');
  62.  
  63.     *psn = info.processNumber;
  64.     
  65.     return noErr;
  66. }
  67.  
  68. OSErr GetSysVolume(short *vRefNum)
  69. {
  70.     long dir;
  71.     
  72.     return FindFolder(kOnSystemDisk, kSystemFolderType, false, vRefNum, &dir);
  73. }
  74.  
  75. OSErr GetIndVolume(short index, short *vRefNum)
  76. {
  77.     OSErr             err;
  78.     ParamBlockRec     pb;
  79.     
  80.     pb.volumeParam.ioNamePtr     = nil;
  81.     pb.volumeParam.ioVolIndex     = index;
  82.     
  83.     FAILOSERR(PBGetVInfoSync(&pb));
  84.     
  85.     *vRefNum = pb.volumeParam.ioVRefNum;
  86.     
  87.     return noErr;
  88. }
  89.  
  90. OSErr VolHasDesktopDB(short vRefNum, Boolean * hasDesktop)
  91. {
  92.     OSErr                         err;
  93.     HParamBlockRec             pb;
  94.     GetVolParmsInfoBuffer     info;
  95.     
  96.     pb.ioParam.ioNamePtr     = nil;
  97.     pb.ioParam.ioVRefNum     = vRefNum;
  98.     pb.ioParam.ioBuffer         = (Ptr)&info;
  99.     pb.ioParam.ioReqCount     = sizeof(GetVolParmsInfoBuffer);
  100.     
  101.     FAILOSERR(PBHGetVolParmsSync(&pb));
  102.  
  103.     *hasDesktop = (info.vMAttrib & (1 << bHasDesktopMgr))!=0;
  104.     
  105.     return noErr;
  106. }
  107.  
  108. OSErr FindAppOnVolume(short vRefNum, FSSpec *file)
  109. {
  110.     OSErr     err;
  111.     DTPBRec     pb;
  112.     
  113.     /* Get Acess path to Desktop database on this volume */
  114.     
  115.     pb.ioVRefNum         = vRefNum;
  116.     pb.ioNamePtr         = nil;
  117.     FAILOSERR(PBDTGetPath(&pb));
  118.     
  119.     pb.ioIndex             = 0;
  120.     pb.ioFileCreator     = 'McPL';
  121.     pb.ioNamePtr         = file->name;
  122.     switch (err = PBDTGetAPPLSync(&pb))    {
  123.     case noErr:
  124.         file->vRefNum     = vRefNum;
  125.         file->parID     = pb.ioAPPLParID;
  126.     
  127.         return noErr;
  128.     case fnfErr:
  129.         return afpItemNotFound;                        /* Bug in PBDTGetAPPL            */
  130.     default:
  131.         return err;
  132.     }
  133. }
  134.  
  135. OSErr LaunchIt(FSSpecPtr fileSpec, ProcessSerialNumber * psn )
  136. {
  137.     OSErr                     err;
  138.     LaunchParamBlockRec     pb;
  139.     
  140.     pb.launchBlockID             = extendedBlock;
  141.     pb.launchEPBLength         = extendedBlockLen;
  142.     pb.launchFileFlags         = launchNoFileFlags;
  143.     pb.launchControlFlags    = launchContinue + launchNoFileFlags;
  144.     pb.launchAppSpec             = fileSpec;
  145.     pb.launchAppParameters    = nil;
  146.     
  147.     FAILOSERR(LaunchApplication(&pb));
  148.  
  149.     *psn = pb.launchProcessSN;
  150.     
  151.     return noErr;
  152. }
  153.  
  154. /* Get the psn ofa copy of MacPerl. Launch one if necessary. Buy one. Steal one. */
  155. static OSErr LaunchMacPerl(ProcessSerialNumber *psn)
  156. {
  157.     OSErr     err;
  158.     short     vRefNum, sysVRefNum, index;
  159.     FSSpec     file;
  160.     Boolean     hasDesktopDB;
  161.     
  162.     /* See if ToolServer is already running:                    */
  163.     err    = MacPerlRunning(psn);
  164.     
  165.     if    (err != procNotFound)
  166.         return err;
  167.     
  168.     /* Not running, try to launch it */
  169.     
  170.     FAILOSERR(GetSysVolume(&sysVRefNum));
  171.     
  172.     vRefNum = sysVRefNum;
  173.     
  174.     for (index = 0; !err; err = GetIndVolume(++index,&vRefNum)) {
  175.         if (!index || vRefNum != sysVRefNum) {
  176.             if (err = VolHasDesktopDB(vRefNum,&hasDesktopDB))
  177.                 return err;
  178.                 
  179.             if (hasDesktopDB)    
  180.                 switch (err = FindAppOnVolume(vRefNum, &file))    {
  181.                 case noErr:
  182.                     return LaunchIt(&file, psn);
  183.                 case afpItemNotFound:
  184.                     break;
  185.                 default:
  186.                     return err;
  187.                 }
  188.         }
  189.     }
  190.     
  191.     switch (err) {
  192.     case nsvErr:
  193.     case afpItemNotFound:
  194.         return fnfErr;
  195.     default:
  196.         return err;
  197.     }
  198. }
  199.  
  200. void WhoAmI(FSSpec * me)
  201. {
  202.     FCBPBRec        fcb;
  203.     
  204.     fcb.ioNamePtr    =    &me->name;
  205.     fcb.ioRefNum    =    CurResFile();
  206.     fcb.ioFCBIndx    =    0;
  207.     
  208.     PBGetFCBInfoSync(&fcb);
  209.     
  210.     me->vRefNum    =    fcb.ioFCBVRefNum;
  211.     me->parID    =    fcb.ioFCBParID;
  212. }
  213.  
  214. pascal OSErr Yo(const AppleEvent *message, AppleEvent *reply, long refcon)
  215. {
  216.     OSErr                        err;
  217.     AppleEvent                doscript;
  218.     ProcessSerialNumber    perl;
  219.     AEAddressDesc            perladdr;
  220.     AEDescList                args;
  221.     AEDescList                incoming;
  222.     AliasHandle                alias;
  223.     AEDesc                    arg;
  224.     AEKeyword                kw;
  225.     
  226.     gQuitting = true;
  227.  
  228.     WaitNextEvent(0, &gLastEvent, 0, nil);
  229.     
  230.     switch (err = LaunchMacPerl(&perl)) {
  231.     case noErr:
  232.         break;
  233.     case fnfErr:
  234.         ParamText(
  235.             "\pFailed to launch MacPerl. Either you don't have MacPerl "
  236.             "or your desktop needs to be rebuilt.", "\p", "\p", "\p");
  237.         Alert(4096, nil);
  238.         
  239.         return err;
  240.     default:
  241.         ParamText(
  242.             "\pFailed to launch MacPerl (possibly because of "
  243.             "a memory problem).", "\p", "\p", "\p");
  244.         Alert(4096, nil);
  245.         
  246.         return err;
  247.     }
  248.     
  249.     FAILOSERR(SetFrontProcess(&perl));
  250.     
  251.     FAILOSERR(
  252.         AECreateDesc(
  253.             typeProcessSerialNumber,
  254.             (Ptr)&perl,
  255.             sizeof(ProcessSerialNumber),
  256.             &perladdr));
  257.     
  258.     if (refcon && (gLastEvent.modifiers & optionKey))
  259.         FAILOSERR(
  260.             AECreateAppleEvent(
  261.                 'McPL', kAEOpenDocuments, &perladdr, 
  262.                 kAutoGenerateReturnID, kAnyTransactionID, 
  263.                 &doscript));
  264.     else
  265.         FAILOSERR(
  266.             AECreateAppleEvent(
  267.                 kAEMiscStandards, kAEDoScript, &perladdr, 
  268.                 kAutoGenerateReturnID, kAnyTransactionID, 
  269.                 &doscript));
  270.     
  271.     FAILOSERR(AECreateList(nil,0,false,&args));
  272.     FAILOSERR(NewAlias(nil,&gMySelf,&alias));
  273.     
  274.     HLock((Handle) alias);
  275.     FAILOSERR(AEPutPtr(&args, 0, typeAlias, (Ptr) *alias, GetHandleSize((Handle) alias)));
  276.     DisposHandle((Handle) alias);
  277.     
  278.     if (!AEGetParamDesc(message, keyDirectObject, typeAEList, &incoming)) {
  279.         short    i = 1;
  280.         
  281.         while (!AEGetNthDesc(&incoming, i++, typeWildCard, &kw, &arg)) {
  282.             FAILOSERR(AEPutDesc(&args, 0, &arg));
  283.             AEDisposeDesc(&arg);
  284.         }
  285.         
  286.         AEDisposeDesc(&incoming);
  287.     }
  288.     
  289.     FAILOSERR(AEPutParamDesc(&doscript, keyDirectObject, &args));
  290.     FAILOSERR(
  291.         AESend(
  292.             &doscript, reply,
  293.             kAENoReply+kAEAlwaysInteract,
  294.             kAENormalPriority, kAEDefaultTimeout,
  295.             nil, nil));
  296.     
  297.     return noErr;
  298. }
  299.  
  300. pascal void MainEvent(void)
  301. {
  302.     if (WaitNextEvent(everyEvent, &gLastEvent, 60, nil))
  303.         switch (gLastEvent.what) {
  304.         case kHighLevelEvent:
  305.             AEProcessAppleEvent(&gLastEvent);
  306.             break;
  307.         }
  308. }
  309.  
  310. void main()
  311. {
  312.     InitGraf(&qd.thePort);
  313.     InitFonts();
  314.     FlushEvents(everyEvent, 0);
  315.     InitWindows();
  316.     InitMenus();
  317.     TEInit();
  318.     InitDialogs(nil);
  319.     InitCursor();
  320.  
  321.     gQuitting          = false;
  322.  
  323.     /*check environment checks to see if we are running 7.0*/
  324.     if (!CheckEnvironment()) {
  325.         SetCursor(&qd.arrow);
  326.         /*pose the only 7.0 alert*/
  327.         ParamText(
  328.             "\pMacPerl droplets need at least System 7.0 to run "
  329.             "(you may run me from the \"MacPerl Runtime\" "
  330.             "application, however).", "\p", "\p", "\p");
  331.         Alert(4096, nil);
  332.         
  333.         ExitToShell();
  334.     }
  335.  
  336.     AEInstallEventHandler( kCoreEventClass, kAEOpenApplication, (EventHandlerProcPtr)Yo, 1, false) ;
  337.     AEInstallEventHandler( kCoreEventClass, kAEOpenDocuments,   (EventHandlerProcPtr)Yo, 0, false) ;
  338.  
  339.     WhoAmI(&gMySelf);
  340.     
  341.     while (!gQuitting)
  342.         MainEvent();
  343. }
  344.